import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import axios from 'axios';
import { createHmac } from 'crypto';

@Injectable()
export class GeeTestService {
  private readonly messageUrl: string;
  private readonly messageAppId: string;
  private readonly messageAppSecret: string;
  private readonly messageModeAuth: string;

  private readonly steUrl: string;
  private readonly steAppId: string;
  private readonly steAppSecret: string;

  private readonly refundId: string;

  constructor(private readonly config: ConfigService) {
    this.messageUrl = this.config.get('geetest.messageUrl');
    this.messageAppId = this.config.get('geetest.messageAppId');
    this.messageAppSecret = this.config.get('geetest.messageAppSecret');
    this.messageModeAuth = this.config.get('geetest.messageModeAuth');

    this.steUrl = this.config.get('geetest.steUrl');
    this.steAppId = this.config.get('geetest.steAppId');
    this.steAppSecret = this.config.get('geetest.steAppSecret');

    this.refundId = this.config.get('geetest.refundId');
  }

  public async sendMessage(
    phone: string,
    params: Record<string, string>,
    modeId?: string,
  ) {
    return await axios
      .post(
        this.messageUrl,
        {
          phone,
          modeId: modeId ?? this.messageModeAuth,
          arguments: params,
        },
        {
          headers: {
            authorization: this.messageAuthorize(),
          },
        },
      )
      .then((res) => res.data);
  }

  public async sendRefund(phone: string) {
    return await this.sendMessage(phone, {}, this.refundId);
  }

  public async simpleThreeElements(
    username: string,
    userid: string,
    phone: string,
  ) {
    return await axios
      .post(
        this.steUrl,
        {
          username,
          userid,
          phone,
        },
        {
          headers: {
            authorization: this.simpleThreeElementsAuthorize(),
            'Content-Type': 'application/x-www-form-urlencoded',
          },
        },
      )
      .then((res) => res.data);
  }

  private messageAuthorize() {
    const timeStamp = Math.floor(Date.now() / 1000);
    const nonce = Math.random().toString(36).substring(2);
    const signature = [timeStamp, nonce, this.messageAppId].sort().join('');
    const hmac = createHmac('sha256', this.messageAppSecret)
      .update(signature)
      .digest('hex');
    return (
      'key=' +
      this.messageAppId +
      ',timestamp=' +
      timeStamp +
      ',nonce=' +
      nonce +
      ',signature=' +
      hmac
    );
  }

  private simpleThreeElementsAuthorize() {
    const timeStamp = Math.floor(Date.now() / 1000);
    const nonce = Math.random().toString(36).substring(2);
    const signature = [timeStamp, nonce, this.steAppId].sort().join('');
    const hmac = createHmac('sha256', this.steAppSecret)
      .update(signature)
      .digest('hex');
    return (
      'gt_id=' +
      this.steAppId +
      ',nonce=' +
      nonce +
      ',signature=' +
      hmac +
      ',timestamp=' +
      timeStamp
    );
  }
}
